#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
import os
import threading
import logging
import re
import asyncio
from datetime import datetime
from bs4 import BeautifulSoup
import db
import download_m3u8

import settings
from logger import set_logger


def get_hls_path():
    return settings.config['hls']['hls_last']


def get_src():
    return settings.config['hls']['src']


def get_poster():
    return settings.config['hls']['poster']


def goto_dir(path):
    data = []
    try:
        session = db.create_session()
        data = [item.dobule_to_dict() for item in session.query(
            db.Hlsitem).filter_by(path=path).order_by(db.Hlsitem.created_at.desc())]
        data.sort(key=lambda el: el['content_type'] != 'd')
    except BaseException as e:
        logging.error('[ERROR] goto_dir: %s' % e)
        data = []
    return {'files': data, 'path': path[1:].split('/')}


def gethls(path):
    try:
        session = db.create_session()
        parent, name = path.rsplit('/', 1)
        if parent:
            data = session.query(db.Hlsitem).filter_by(
                path=parent, name=name).first()
    except BaseException as e:
        logging.error('[ERROR] gethls: %s' % e)
        data = None
    return {'video': data, 'path': path[1:].split('/')}


def delete_by_path(parent, name):
    try:
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if hlsitem.content_type == 'd':
            dir_ = '%s/%s' % (parent, name)
            # session.query(db.Hlsitem).filter(db.Hlsitem.path.like('%s%%' % dir_)).delete(synchronize_session=False)
            # session.query(db.Hlsitem).filter_by(db.Hlsitem.path.like('%s%%' % dir_), db.Hlsitem.status=0)
            if len([item for item in session.query(db.Hlsitem).filter(db.Hlsitem.path.like('%s%%' % dir_), db.Hlsitem.status == 0)]) > 0:
                raise BaseException(
                    '文件夹[%s/%s]存在状态[%s]是下载中的文件,不能删除该文件夹' % (parent, name, '0'))
            for item in session.query(db.Hlsitem).filter(db.Hlsitem.path.like('%s%%' % dir_)):
                result = delete(item.path, item.name)
                if not result['status']:
                    raise BaseException(result['msg'])
            session.delete(hlsitem)
            session.commit()
            return {'status': True, 'msg': "成功"}
        else:
            if hlsitem.status == 0:
                raise BaseException(
                    '文件[%s/%s]状态[%s]是下载中,不能删除该文件' % (parent, name, hlsitem.status))
            return delete(parent, name)
    except BaseException as e:
        return {'status': False, 'msg': e}


def delete(parent, name):
    session = db.create_session()
    hlsitem = session.query(db.Hlsitem).filter_by(
        name=name, path=parent).first()
    if not hlsitem:
        logging.error('[-]file[%s/%s] not exits: %s' % (parent, name))
        return {'status': True, 'msg': 'file[%s/%s] not exits: %s' % (parent, name)}
    url = hlsitem.referer
    path = '%s/%s' % (get_hls_path(),
                      url[url.index('://')+3:url.rindex('/')].replace(':', '_'))
    result = rmdir(path)
    logging.warning('[-]result: %s' % result)
    session.delete(hlsitem)
    session.commit()
    return {'status': True, 'msg': "成功"}


def rmdir(top_dir):
    if os.path.exists(top_dir) == False:
        return {'status': False, 'msg': "%s not exists" % top_dir}
    if os.path.isdir(top_dir) == False:
        return {'status': False, 'msg': "%s not a dir" % top_dir}
    for dir_path, subpaths, files in os.walk(top_dir, False):
        for file in files:
            file_path = os.path.join(dir_path, file)
            logging.warning("delete file:%s" % file_path)
            os.remove(file_path)
        logging.warning("delete dir:%s" % dir_path)
        os.rmdir(dir_path)
    return {'status': True, 'msg': "成功"}


def rename(fullpath, newname):
    try:
        session = db.create_session()
        parent, name = fullpath.rsplit('/', 1)
        if '/' in newname:
            return {'status': False, 'msg': '文件名[%s]包含"/"' % newname}
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=newname, path=parent).first()
        if hlsitem:
            return {'status': False, 'msg': '文件[%s/%s]已存在' % (parent, newname)}
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if not hlsitem:
            return {'status': False, 'msg': '文件[%s]不存在' % fullpath}
        if hlsitem.content_type == 'd':
            child_files = session.query(db.Hlsitem).filter(
                db.Hlsitem.path.like('%s%%' % fullpath))
            for item in child_files:
                if item.status == 0:
                    raise BaseException(
                        '文件夹[%s]存在下载中的任务[%s/%s],不能重命名该文件夹' % (fullpath, item.path, item.name))
                item.path = '%s/%s' % (parent, newname)
            hlsitem.name = newname
            hlsitem.updated_at = datetime.now()
            session.commit()
        else:
            if hlsitem.status == 0:
                raise BaseException(
                    '文件[%s]状态[%s]是正在下载中,不能重命名该文件' % (fullpath, hlsitem.status))
            hlsitem.name = newname
            hlsitem.updated_at = datetime.now()
            session.commit()
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': '重命名成功'}


def move(fullpath, newpath):
    try:
        session = db.create_session()
        parent, name = newpath.rsplit('/', 1)
        if len(parent) <= 0:
            parent = None
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if not hlsitem:
            return {'status': False, 'msg': '目标路径[%s]不存在' % newpath}
        if hlsitem.content_type != 'd':
            return {'status': False, 'msg': '目标路径[%s]不是文件夹' % newpath}
        parent, name = fullpath.rsplit('/', 1)
        if len(parent) <= 0:
            return {'status': False, 'msg': '根目录[%s]不能移动' % fullpath}
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=newpath).first()
        if hlsitem:
            {'status': False, 'msg': '目标路径[%s]存在[%s]同名文件' % (newpath, name)}
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if not hlsitem:
            return {'status': False, 'msg': '源文件[%s]不存在' % fullpath}
        if hlsitem.content_type == 'd':
            child_files = session.query(db.Hlsitem).filter(
                db.Hlsitem.path.like('%s%%' % fullpath))
            for item in child_files:
                if item.status == 0:
                    raise BaseException(
                        '文件夹[%s]存在下载中的任务[%s/%s],不能移动该文件' % (fullpath, item.path, item.name))
                item.path = '%s/%s' % (newpath, name)
            hlsitem.path = newpath
            hlsitem.updated_at = datetime.now()
            session.commit()
        else:
            if hlsitem.status == 0:
                raise BaseException(
                    '文件[%s]状态[%s]是正在下载中,不能移动该文件' % (fullpath, hlsitem.status))
            hlsitem.path = newpath
            hlsitem.updated_at = datetime.now()
            session.commit()
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': '移动成功'}


def offline_download(parent, name, url):
    '''
    子线程下载m3u8文件
    :param parent: m3u8文件所在文件夹
    :param name: m3u8文件名
    :param url: m3u8文件下载地址
    '''
    try:
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if not hlsitem:
            logging.error('[-]file[%s/%s] not exists' % (parent, name))
            return
        result = {}
        path = ''
        uri = ''
        m3u8_name = download_m3u8.resource_name(url)
        if hlsitem.url and hlsitem.url.endswith(m3u8_name):
            uri = hlsitem.url
            path = '%s/%s' % (get_hls_path(), uri.rsplit('/', 1)[0])
        else:
            referer = hlsitem.referer_referer
            uri = '%s/%s' % (referer[referer.index('://') +
                                     3:].replace(':', '_'), m3u8_name)
            path = '%s/%s' % (get_hls_path(),
                              referer[referer.index('://')+3:].replace(':', '_'))
        download_m3u8.downloadm3u8(url, path, result, m3u8_name)
        run_key = {}
        download_m3u8.download_ts(result, run_key=run_key)
        duration = 0
        for key in result.keys():
            if isinstance(result[key], dict) and 'duration' in result[key].keys():
                duration = int(result[key]['duration'])
        size = run_key.get('size', 0)
        logging.warning('[-]duration: %s, size: %s' %
                        (duration, run_key['size']))
        if run_key.get(0, True):
            hlsitem.status = 1
            hlsitem.url = uri
            hlsitem.duration = duration
            hlsitem.size = size
            hlsitem.updated_at = datetime.now()
            session.commit()
        else:
            logging.warning('download task pause, need to restart')
            hlsitem = session.query(db.Hlsitem).filter_by(
                name=name, path=parent).first()
            # -1: 暂停
            hlsitem.status = -1
            hlsitem.updated_at = datetime.now()
            session.commit()
    except BaseException as e:
        logging.error('[-]%s: %s' % (threading.current_thread().name, e))
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        # -1: 暂停
        hlsitem.status = -1
        hlsitem.updated_at = datetime.now()
        session.commit()


def load_poster(parent, name, url):
    '''
    子线程下载封面
    :param parent: m3u8文件所在文件夹
    :param name: m3u8文件名
    :param url: 封面下载地址
    '''
    try:
        result = {}
        uri = url[url.index('://')+3:].replace(':', '_')
        path = '%s/%s' % (get_poster(), uri.rsplit('/', 1)
                          [0].replace(':', '_'))
        download_m3u8.downloadtask([url], path)
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        hlsitem.poster = uri
        hlsitem.updated_at = datetime.now()
        session.commit()
    except BaseException as e:
        logging.error('[-]%s: %s' % (threading.current_thread().name, e))


def offline(parent, url, name, referer, poster_referer):
    try:
        session = db.create_session()
        if len([item for item in session.query(db.Hlsitem).filter_by(name=name, path=parent)]) > 0:
            return {'status': False, 'msg': '文件[%s/%s]重名' % (parent, name)}
        # 0: 下载中
        hlsitem = db.Hlsitem(status=0, name=name, path=parent, content_type='-',
                             referer=url, referer_referer=referer, poster_referer=poster_referer)
        session.add(hlsitem)
        session.commit()
        # 子线程下载m3u8文件
        offline_download_t = threading.Thread(
            target=offline_download, name='offline_download-%s/%s' % (parent, name), args=(parent, name, url))
        offline_download_t.setDaemon(True)
        offline_download_t.start()
        # 子线程下载封面
        if poster_referer and len(poster_referer) > 0:
            load_poster_t = threading.Thread(
                target=load_poster, name='load_poster-%s/%s' % (parent, name), args=(parent, name, poster_referer))
            load_poster_t.setDaemon(True)
            load_poster_t.start()
    except BaseException as e:
        hlsitem = session.query(db.Hlsitem).filter_by(name=name, path=parent)
        hlsitem.status = -1
        hlsitem.updated_at = datetime.now()
        session.commit()
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': '成功'}


def restart(parent, name):
    try:
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if not hlsitem:
            return {'status': False, 'msg': '文件[%s/%s]不存在' % (parent, name)}
        # -1: 已暂停
        if hlsitem.status != -1:
            return {'status': False, 'msg': '该文件[%s/%s]状态[%s]不是已暂停' % (parent, name, hlsitem.status)}
        url = hlsitem.referer
        hlsitem.status = 0
        hlsitem.updated_at = datetime.now()
        session.commit()
        # 子线程下载m3u8文件
        upload_parse_t = threading.Thread(
            target=offline_download, name='offline_download-%s/%s' % (parent, name), args=(parent, name, url))
        upload_parse_t.setDaemon(True)
        upload_parse_t.start()
    except BaseException as e:
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        hlsitem.status = -1
        hlsitem.updated_at = datetime.now()
        session.commit()
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': '成功'}


def status(parent, name):
    try:
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if not hlsitem:
            return {'status': False, 'msg': '文件[%s/%s]不存在' % (parent, name)}
        # 0: 下载中
        if hlsitem.status != 0:
            return {'status': False, 'msg': '文件[%s/%s]状态[%s]不是下载中' % (parent, name, hlsitem.status)}
        url = hlsitem.referer_referer
        path = '%s/%s' % (get_hls_path(),
                          url[url.index('://')+3:].replace(':', '_'))
        flag = False
        buf = ''
        for root, dirs, files in os.walk(path):
            for file in files:
                if file == 'status.tmp':
                    with open(os.path.join(root, file), 'r') as tmp_file:
                        buf += '%s: %s\n' % (root, tmp_file.read().strip())
                    flag = True
        if not flag:
            return {'status': False, 'msg': 'status.tmp not found'}
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': buf}


def pause(parent, name):
    try:
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if not hlsitem:
            return {'status': False, 'msg': '文件[%s/%s]不存在' % (parent, name)}
        # 0: 下载中
        if hlsitem.status != 0:
            return {'status': False, 'msg': '文件[%s/%s]状态[%s]不是下载中' % (parent, name, hlsitem.status)}
        url = hlsitem.referer_referer
        path = '%s/%s' % (get_hls_path(),
                          url[url.index('://')+3:].replace(':', '_'))
        flag = False
        for root, dirs, files in os.walk(path):
            for file in files:
                if file == 'status.tmp':
                    os.remove(os.path.join(root, file))
                    flag = True
        if not flag:
            return {'status': False, 'msg': 'status.tmp not found'}
        hlsitem.status = -1
        hlsitem.updated_at = datetime.now()
        session.commit()
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': '成功'}


def mkdirs(fullpath):
    session = db.create_session()
    ppath, pname = fullpath.rsplit('/', 1)
    if len(ppath) > 0:
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=pname, path=ppath).first()
        if hlsitem:
            return
        mkdirs(ppath)
        hlsitem = db.Hlsitem(status=1, name=pname,
                             path=ppath, content_type='d')
        session.add(hlsitem)
        session.commit()
    else:
        parent, name = (None, pname)
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if hlsitem:
            return


def import_data(data):
    additem = []
    try:
        session = db.create_session()
        paths = []
        fileitem_exists = []
        fileitem_not_exists = []
        logging.warning('data: %s' % data)
        for item in data:
            if 'content_type' in item:
                if item['content_type'] != 'd':
                    if not 'referer_referer' in item or not 'referer' in item:
                        logging.error('[-]文件[%s/%s]格式不正确: %s' %
                                      (item['path'], item['name'], item))
                        return {'status': False, 'msg': '文件[%s/%s]格式不正确: %s' % (item['path'], item['name'], item)}
                if not 'name' in item or not 'path' in item:
                    logging.error('[--]文件[%s/%s]格式不正确: %s' %
                                  (item['path'], item['name'], item))
                    return {'status': False, 'msg': '文件[%s/%s]格式不正确: %s' % (item['path'], item['name'], item)}
            else:
                logging.error('[---]文件[%s/%s]格式不正确: %s' %
                              (item['path'], item['name'], item))
                return {'status': False, 'msg': '文件[%s/%s]格式不正确: %s' % (item['path'], item['name'], item)}
            hlsitem = session.query(db.Hlsitem).filter_by(
                name=item['name'], path=item['path']).first()
            if hlsitem:
                logging.warning('[-]文件[%s/%s]已存在' %
                                (item['path'], item['name']))
                fileitem_exists.append(item)
            else:
                fileitem_not_exists.append(item)
                if item['path'] in paths:
                    continue
                paths.append(item['path'])
        logging.warning('fileitem_exists: %s' % fileitem_exists)
        logging.warning('fileitem_not_exists: %s' % fileitem_not_exists)
        for path in paths:
            mkdirs(path)
        for item in fileitem_not_exists:
            # -1: 下载已暂停
            hlsitem = db.Hlsitem(status=-1, name=item['name'], path=item['path'], content_type='-',
                                 poster_referer=item['poster_referer'], referer=item['referer'], referer_referer=item['referer_referer'])
            session.add(hlsitem)
            # 子线程下载封面
            if item['poster_referer'] and len(item['poster_referer']) > 0:
                load_poster_t = threading.Thread(target=load_poster, name='load_poster-%s/%s' % (
                    item['path'], item['name']), args=(item['path'], item['name'], item['poster_referer']))
                load_poster_t.setDaemon(True)
                load_poster_t.start()
            session.commit()
            hlstmp = session.query(db.Hlsitem).filter_by(
                name=item['name'], path=item['path']).first()
            additem.append(hlstmp)
        # for item in fileitem_exists:
        #     if item['content_type'] == 'd':
        #         hlsitem = session.query(db.Hlsitem).filter_by(
        #             name=item['name'], path=item['path']).first()
        #         hlsitem.poster_referer = item['poster_referer']
        #         session.commit()
        #     else:
        #         # -1: 下载已暂停
        #         hlsitem = session.query(db.Hlsitem).filter_by(
        #             name=item['name'], path=item['path']).first()
        #         poster = item['poster'] if item['poster'] else hlsitem.poster
        #         hlsitem.poster_referer = item['poster_referer']
        #         hlsitem.poster = poster
        #         hlsitem.referer = item['referer']
        #         hlsitem.referer_referer = item['referer_referer']
        #         session.commit()
        #     # 子线程下载封面
        #     if item['poster_referer'] and len(item['poster_referer']) > 0:
        #         load_poster_t = threading.Thread(target=load_poster, name='load_poster-%s/%s' % (
        #             item['path'], item['name']), args=(item['path'], item['name'], item['poster_referer']))
        #         load_poster_t.setDaemon(True)
        #         load_poster_t.start()
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': additem}


def export(parent, name):
    try:
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if not hlsitem:
            return {'status': False, 'msg': '文件[%s/%s]不存在' % (parent, name)}
        # 0: 下载中
        result = []
        if hlsitem.content_type == 'd':
            fullpath = '%s/%s' % (parent, name)
            if not parent:
                fullpath = name
            result.append({'path': hlsitem.path, 'name': hlsitem.name,
                           'content_type': hlsitem.content_type, 'referer': hlsitem.referer})
            child_files = session.query(db.Hlsitem).filter(
                db.Hlsitem.path.like('%s%%' % fullpath))
            for item in child_files:
                result.append({'path': item.path, 'name': item.name, 'content_type': item.content_type, 'referer': item.referer,
                               'referer_referer': item.referer_referer, 'poster': item.poster, 'poster_referer': item.poster_referer})
        else:
            result.append({'path': hlsitem.path, 'name': hlsitem.name, 'content_type': hlsitem.content_type, 'referer': hlsitem.referer,
                           'referer_referer': hlsitem.referer_referer, 'poster': hlsitem.poster, 'poster_referer': hlsitem.poster_referer})
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': result}


def hls_export(fullpath):
    try:
        parent, name = fullpath.rsplit('/', 1)
        if len(parent) <= 0:
            parent = None
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            path=parent, name=name).first()
        if not hlsitem:
            return {'status': False, 'msg': '文件[%s/%s]不存在' % (parent, name)}
        # 0: 下载中
        result = []
        if hlsitem.content_type == 'd':
            return {'status': False, 'msg': '文件[%s/%s]不是hls文件' % (parent, name)}
        else:
            result.append({'path': hlsitem.path, 'name': hlsitem.name, 'content_type': 'hls', 'referer': hlsitem.referer,
                           'referer_referer': hlsitem.referer_referer, 'poster': hlsitem.poster, 'poster_referer': hlsitem.poster_referer})
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': result}


def get_hls(path):
    try:
        session = db.create_session()
        ppath, pname = path.rsplit('/', 1)
        hlsitem = session.query(db.Hlsitem).filter_by(
            path=ppath, name=pname).first()
        if hlsitem:
            if hlsitem.content_type == 'd':
                return {'status': False, 'msg': '路径[%s]是文件' % path}
            else:
                return {'status': True, 'msg': {'path': '%s/%s' % (hlsitem.path, hlsitem.name), 'status': hlsitem.status, 'referer': hlsitem.referer, 'poster_referer': hlsitem.poster_referer, 'referer_referer': hlsitem.referer_referer, 'url': hlsitem.url}}
        else:
            return {'status': False, 'msg': '路径[%s]指向的文件不存在' % path}
    except BaseException as e:
        return {'status': False, 'msg': e}


def makedir(parent, name):
    try:
        session = db.create_session()
        pparent, parent_name = parent.rsplit('/', 1)
        if len(pparent) <= 0:
            pparent = None

        if len([item for item in session.query(db.Hlsitem).filter_by(name=parent_name, path=pparent, content_type='d')]) <= 0:
            return {'status': False, 'msg': '父文件夹(%s)不存在' % parent}
        if len([item for item in session.query(db.Hlsitem).filter_by(name=name, path=parent)]) > 0:
            return {'status': False, 'msg': '文件[%s/%s]重名' % (parent, name)}
        hlsitem = db.Hlsitem(status=1, name=name,
                             path=parent, content_type='d')
        session.add(hlsitem)
        session.commit()
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': '成功'}


def update(parent, name, status, referer, referer_referer, poster_referer, url):
    '''
    更新Hlsitem表数据
    :param parent: 文件所在文件夹
    :param name: 文件名
    :param status: 文件状态(-1: 已暂停, 0: 下载中, 1: 下载完成)
    :param referer: m3u8下载地址
    :param referer_referer: 源地址
    :param poster_referer: 封面源地址
    :param url: 播放URI
    :return {'status': True, 'msg': '成功'}
    '''
    try:
        session = db.create_session()
        hlsitem = session.query(db.Hlsitem).filter_by(
            name=name, path=parent).first()
        if not hlsitem:
            logging.error('文件[%s/%s]不存在' % (parent, name))
            return {'status': False, 'msg': '文件[%s/%s]不存在' % (parent, name)}
        hlsitem.status = status
        hlsitem.referer = referer
        hlsitem.referer_referer = referer_referer
        hlsitem.poster_referer = poster_referer
        hlsitem.url = url
        hlsitem.updated_at = datetime.now()
        session.commit()
        # 子线程下载封面
        if poster_referer and len(poster_referer) > 0:
            load_poster_t = threading.Thread(
                target=load_poster, name='load_poster-%s/%s' % (parent, name), args=(parent, name, poster_referer))
            load_poster_t.setDaemon(True)
            load_poster_t.start()
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': '成功'}


def download_src(url, path, name):
    '''
    下载源页面,子线程使用
    '''
    filepath = '%s/%s' % (path, name)
    os.makedirs(path, exist_ok=True)
    if os.path.exists(filepath):
        logging.warning('[-]remove file %s' % filepath)
        os.remove(filepath)
    download_m3u8.download(url, filepath)
    logging.info('[-]get file[%s] %s complete' % (filepath, url))


def load_src(url, dom_path, get_res, mode=0):
    '''
    获取源信息
    :param url: 源页面url
    :param dom_path: 节点路径
    :param get_res: 节点处理
    :param mode: 加载源信息的方式(0-下载页面,1-解析页面)
    :return {'status': True, 'msg': result}
    '''
    # url = 'http://m.q2vod.com/k-94f491603c460cc71b76a3c7b7530ade/e-1588154204/96/96-KmSzWs1oDA0OsEPzeJZQ.m3u8'
    # url = 'https://s19.xyz/video/view/eympOn3rAoMNa7Vq'
    # dom_path = [{'video': {'attr': {'id': 'video-play'}, 'string': ''}}]
    # get_res = {'attrs': ['data-src', 'data-poster']}
    # url = 'http://flsav6.xyz/index.php/vod/play/id/15167/sid/1/nid/1.html'
    # dom_path = [{'script': {'string': 'player_data'}}]
    # get_res = {'string': 'player_data'}
    try:
        path = '%s/%s' % (get_src(),
                          url[url.index('://')+3:url.rindex('/')].replace(':', '_'))
        cur_file_name = download_m3u8.resource_name(url)
        filepath = '%s/%s' % (path, cur_file_name)
        result = ''
        if mode == '0':
            download_src_t = threading.Thread(
                target=download_src, name='download_src-%s[%s]' % (url, filepath), args=(url, path, cur_file_name))
            download_src_t.setDaemon(True)
            download_src_t.start()
            result = '> 获取信息中...'
        elif mode == '1':
            all_content = ''
            with open(filepath, 'r') as m3u8:
                all_content = m3u8.read()
            # print(all_content)
            # return
            soup = BeautifulSoup(all_content, features='html.parser')
            # items = soup.find_all('video', {'id': 'video-play'})
            logging.info('url: %s, dom_path: %s, get_res: %s' %
                         (url, dom_path, get_res))
            if isinstance(dom_path, list):
                for dom in dom_path:
                    key, val = list(dom.items())[0]
                    soup = soup.find_all(key, val.get(
                        'attr', None), string=re.compile(val.get('string', None)))
            result = str(soup) if '\\' not in str(
                soup) else str(soup).replace('\\', '')
            if isinstance(get_res, dict) and len(get_res) > 0:
                result = []
                for item in soup:
                    attrs = get_res.get('attrs', None)
                    string = get_res.get('string', None)
                    if attrs:
                        value = {}
                        for attr in attrs:
                            value[attr] = item.get(attr, None)
                        result.append(value)
                    if string:
                        result.append(
                            item.string if '\\' not in item.string else item.string.replace('\\', ''))
            if len(result) <= 0:
                result = [all_content]
    except BaseException as e:
        logging.error('Error: %s' % e)
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': result}


def update_poster(fullpath):
    try:
        if not fullpath.startswith('/root'):
            raise BaseException('fullpath[%s] not start with /root' % fullpath)
        session = db.create_session()
        path, name = fullpath.rsplit('/', 1)
        if len(path) <= 0:
            path = None
        hlsitem = session.query(db.Hlsitem).filter_by(
            path=path, name=name).first()
        if not hlsitem:
            raise BaseException('文件[%s]不存在' % fullpath)
        if hlsitem.content_type == 'd':
            for item in session.query(db.Hlsitem).filter(db.Hlsitem.path.like('%s%%' % fullpath)):
                update_poster('%s/%s' % (item.path, item.name))
            return {'status': True, 'msg': fullpath}
        else:
            # 子线程下载封面
            if hlsitem.poster_referer and len(hlsitem.poster_referer) > 0:
                load_poster_t = threading.Thread(target=load_poster, name='load_poster-%s/%s' % (
                    hlsitem.path, hlsitem.name), args=(hlsitem.path, hlsitem.name, hlsitem.poster_referer))
                load_poster_t.setDaemon(True)
                load_poster_t.start()
    except BaseException as e:
        return {'status': False, 'msg': e}
    logging.info('%s--------END---------' % threading.current_thread().name)
    return {'status': True, 'msg': fullpath.rsplit('/', 1)[0]}


async def update_july_data_async(fullpath):
    if not fullpath.startswith('/root'):
        raise BaseException('fullpath[%s] not start with /root' % fullpath)
    session = db.create_session()
    if '/root' == fullpath:
        path, filetype = (None, '/root')
    path, name = fullpath.rsplit('/', 1)
    hlsitem = session.query(db.Hlsitem).filter_by(path=path, name=name).first()
    if not hlsitem:
        raise BaseException('文件[%s]不存在' % fullpath)
    logging.info('-------------------------')
    logging.info('[-]hlsitem: %s' % hlsitem)
    logging.info('-------------------------')
    if hlsitem.content_type != 'd':
        url = hlsitem.referer_referer
        filepath = '%s/%s' % (get_src(),
                              url[url.index('://')+3:url.rindex('/')].replace(':', '_'))
        cur_file_name = download_m3u8.resource_name(url)
        download_src(url, filepath, cur_file_name)
        dom_path = [{'video': {'attr': {'id': 'video-play'}, 'string': ''}}]
        get_res = {'attrs': ['data-src', 'data-poster']}
        result = load_src(url, dom_path, get_res, mode='1')
        logging.info('[-]result: %s' % result)
        if result['status']:
            data_src = '%s%s' % (
                url.split('//', 1)[0], result['msg'][0]['data-src'])
            data_poster = '%s%s' % (
                url.split('//', 1)[0], result['msg'][0]['data-poster'])
            logging.info('[+]src: %s, poster: %s' % (data_src, data_poster))
            hlsitem.referer = data_src
            hlsitem.poster_referer = data_poster
            hlsitem.updated_at = datetime.now()
            session.commit()
            logging.info(
                '----------------------------------------------------------------------')
            logging.info('------%s/%s update complete' %
                         (hlsitem.path, hlsitem.name))
            logging.info(
                '----------------------------------------------------------------------')
        else:
            logging.warning('[-] failed to parse %s: %s' %
                            (fullpath, result['msg']))
    else:
        logging.info('[-] hlsitem[%s] is directory' % fullpath)
    logging.info('--------END---------')


def import_july_data(filepath):
    if not os.path.exists(filepath):
        raise BaseException('[-]file(%s) not exists' % filepath)
    with open(filepath, 'r') as list_file:
        all_content = list_file.read()
    if len(all_content) <= 0:
        raise BaseException("Failed to download list file: \n%s" % all_content)
    if '\r\n' in all_content:
        file_line = all_content.split("\r\n")
    else:
        file_line = all_content.split("\n")
    result = []
    for item in file_line:
        if not item or len(item) <= 0:
            break
        logging.info('[-]start get %s' % item)
        tmppath = '%s/%s' % (get_src(),
                             item[item.index('://')+3:item.rindex('/')].replace(':', '_'))
        cur_file_name = download_m3u8.resource_name(item)
        download_src(item, tmppath, cur_file_name)

        with open('%s/%s' % (tmppath, cur_file_name), 'r') as html_file:
            all_content = html_file.read()
        soup = BeautifulSoup(all_content, features='html.parser')
        referer = '%s%s' % (item.split(
            '//', 1)[0], soup.find('video')['data-src'])
        poster_referer = '%s%s' % (item.split(
            '//', 1)[0], soup.find('video')['data-poster'])
        poster = '-'
        referer_referer = item
        content_type = '-'
        name = soup.find('h4', {'class': 'container-title'}).string
        path = '/root/july'
        data = {
            'referer': referer,
            'poster_referer': poster_referer,
            'poster': poster,
            'referer_referer': referer_referer,
            'content_type': content_type,
            'name': name,
            'path': path
        }
        result.append(data)
        logging.info('[-]end %s' % item)

    print(result)


def import_fuliseav_data(filepath):
    if not os.path.exists(filepath):
        raise BaseException('[-]file(%s) not exists' % filepath)
    with open(filepath, 'r') as list_file:
        all_content = list_file.read()
    if len(all_content) <= 0:
        raise BaseException("Failed to download list file: \n%s" % all_content)
    if '\r\n' in all_content:
        file_line = all_content.split("\r\n")
    else:
        file_line = all_content.split("\n")
    result = []
    for index, item in enumerate(file_line):
        if not item or len(item) <= 0:
            break
        logging.info('[-]start get %s' % item)
        tmppath = '%s/%s' % (get_src(),
                             item[item.index('://')+3:item.rindex('/')].replace(':', '_'))
        cur_file_name = download_m3u8.resource_name(item)
        logging.info('-' * 65)
        logging.info('%s in %s' % (index, len(file_line) - 1))
        logging.info('-' * 65)
        if not os.path.exists('%s/%s' % (tmppath, cur_file_name)):
            download_src(item, tmppath, cur_file_name)

        with open('%s/%s' % (tmppath, cur_file_name), 'r') as html_file:
            all_content = html_file.read()
        soup = BeautifulSoup(all_content, features='html.parser')
        dom_referer = soup.find(string=re.compile("player_data"))
        # print(dom_referer)
        # print(re.search('"url":"(.+)","url_next"', dom_referer.string).group(1).replace('\/', '/'))
        referer = re.search('"url":"(.+)","url_next"',
                            dom_referer.string).group(1).replace('\/', '/')
        # meta property="og:image"
        poster_referer = soup.find('meta', {'property': 'og:image'})[
            'content'].strip()
        poster = '-'
        referer_referer = item
        content_type = '-'
        # meta property="og:description"
        name = soup.find('meta', {'property': 'og:description'})[
            'content'].strip().replace(':', '')
        path = '/root/flsav'
        data = {
            'referer': referer,
            'poster_referer': poster_referer,
            'poster': poster,
            'referer_referer': referer_referer,
            'content_type': content_type,
            'name': name,
            'path': path
        }
        result.append(data)
        logging.info('[-]end %s' % item)
        # break
    print(result)


def import_521_data(filepath):
    if not os.path.exists(filepath):
        raise BaseException('[-]file(%s) not exists' % filepath)
    with open(filepath, 'r') as list_file:
        all_content = list_file.read()
    if len(all_content) <= 0:
        raise BaseException("Failed to download list file: \n%s" % all_content)
    if '\r\n' in all_content:
        file_line = all_content.split("\r\n")
    else:
        file_line = all_content.split("\n")
    result = []
    for item in file_line:
        if not item or len(item) <= 0:
            break
        logging.info('[-]start get %s' % item)
        tmppath = '%s/%s' % (get_src(),
                             item[item.index('://')+3:item.rindex('/')].replace(':', '_'))
        cur_file_name = download_m3u8.resource_name(item)
        download_src(item, tmppath, cur_file_name)

        with open('%s/%s' % (tmppath, cur_file_name), 'r') as html_file:
            all_content = html_file.read()
        soup = BeautifulSoup(all_content, features='html.parser')
        dom_referer = soup.find(string=re.compile("var playurl"))
        referer_str = re.search(
            'kele\(\'(.+)\'\)', dom_referer.string).group(1)
        referer = '%s/%s.%s' % ('https://pppp.363ub.com',
                                referer_str[referer_str.index('://') + 3:].split('/', 1)[1], 'm3u8')
        poster_referer = re.search(
            'poster : \'(.+)\',', dom_referer.string).group(1)
        name_dom = soup.select('*.cat_pos_l a')[-1]
        poster = '-'
        referer_referer = '%s%s%s' % (item[:item.index(
            '://') + 3], item[item.index('://') + 3:].split('/', 1)[0], name_dom['href'])
        name = name_dom.string
        content_type = '-'
        path = '/root/521av'
        data = {
            'referer': referer,
            'poster_referer': poster_referer,
            'poster': poster,
            'referer_referer': referer_referer,
            'content_type': content_type,
            'name': name,
            'path': path
        }
        result.append(data)
        logging.info('[-]end %s' % item)
        # break
    print(result)


def update_july_data(fullpath):
    if not fullpath.startswith('/root'):
        raise BaseException('fullpath[%s] not start with /root' % fullpath)
    session = db.create_session()
    if '/root' == fullpath:
        path, filetype = (None, '/root')
    path, name = fullpath.rsplit('/', 1)
    hlsitem = session.query(db.Hlsitem).filter_by(path=path, name=name).first()
    if not hlsitem:
        raise BaseException('文件[%s]不存在' % fullpath)
    logging.info('-------------------------')
    logging.info('[-]hlsitem: %s' % hlsitem)
    logging.info('-------------------------')
    if hlsitem.content_type == 'd':
        items = ['%s/%s' % (item.path, item.name) for item in session.query(
            db.Hlsitem).filter(db.Hlsitem.path.like('%s%%' % fullpath))]
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        tasks = [update_july_data_async(item) for item in items]
        try:
            loop.run_until_complete(asyncio.wait(tasks))
        except KeyboardInterrupt as e:
            logging.info(asyncio.Task.all_tasks())
            for task in asyncio.Task.all_tasks():
                logging.info(task.cancel())
            loop.stop()
        except BaseException as e:
            logging.error('[-]ERROR: %s' % e)
        # for item in session.query(db.Hlsitem).filter(db.Hlsitem.path.like('%s%%' % fullpath)):
        #     update_july_data('%s/%s' % (item.path, item.name))
    else:
        url = hlsitem.referer_referer
        filepath = '%s/%s' % (get_src(),
                              url[url.index('://')+3:url.rindex('/')].replace(':', '_'))
        cur_file_name = download_m3u8.resource_name(url)
        download_src(url, filepath, cur_file_name)
        dom_path = [{'video': {'attr': {'id': 'video-play'}, 'string': ''}}]
        get_res = {'attrs': ['data-src', 'data-poster']}
        result = load_src(url, dom_path, get_res, mode='1')
        # print(result)
        if result['status']:
            data_src = '%s%s' % (
                url.split('//', 1)[0], result['msg'][0]['data-src'])
            data_poster = '%s%s' % (
                url.split('//', 1)[0], result['msg'][0]['data-poster'])
            logging.info('[+]src: %s, poster: %s' % (data_src, data_poster))
            hlsitem.referer = data_src
            hlsitem.poster_referer = data_poster
            hlsitem.updated_at = datetime.now()
            session.commit()
            logging.info(
                '----------------------------------------------------------------------')
            logging.info('------%s/%s update complete' %
                         (hlsitem.path, hlsitem.name))
            logging.info(
                '----------------------------------------------------------------------')
    logging.info('--------END---------')


def load_local(top_dir):
    if os.path.exists(top_dir) == False:
        return {'status': False, 'msg': "%s not exists" % top_dir}
    if os.path.isdir(top_dir) == False:
        return {'status': False, 'msg': "%s not a dir" % top_dir}
    local_files = []
    for dir_path, subpaths, files in os.walk(top_dir, False):
        for file in files:
            if file.endswith('.m3u8'):
                file_path = os.path.join(dir_path, file)
                local_files.append(file_path)
    # logging.warning("m3u8 file:%s"  %local_files)
    local_d = {}
    for file in local_files:
        fullpath = re.match('%s/(.+)' %
                            get_hls_path().split('/', 1)[1], file).group(1)
        path, name = fullpath.rsplit('/', 1)
        local_d[path] = name
    sub_dir = []
    for key in local_d.keys():
        for key_ in local_d.keys():
            if key_.startswith(key) and key_ != key:
                sub_dir.append(key_)
    for item in sub_dir:
        if item in local_d.keys():
            local_d.pop(item)
    for k, v in local_d.items():
        print('%s/%s' % (k, v))


def update_fuliseav_data():
    print('%supdate_fuliseav_data%s\n' % ('-' * 35, '-' * 5))
    session = db.create_session()
    flsitems = [item for item in session.query(db.Hlsitem).filter(
        db.Hlsitem.path.like('%s%%' % '/root/flsav'))]
    for item in flsitems:
        if item.url is None:
            continue
        m3u8_path = '%s/%s' % (get_hls_path(), item.url)
        handle_m3u8(m3u8_path)
    print('%supdate_fuliseav_data%s\n' % ('-' * 35, '-' * 35))


def handle_m3u8(m3u8_path):
    if not os.path.exists(m3u8_path):
        return
    print('current m3u8 file: %s' % m3u8_path)
    with open(m3u8_path, 'r') as file:
        all_content = file.read()
    if '\r\n' in all_content:
        file_line = all_content.split("\r\n")
    else:
        file_line = all_content.split("\n")
    if file_line[0] != "#EXTM3U":
        return
    cur_path = m3u8_path.rsplit('/', 1)[0]
    # with open(m3u8_path, 'w') as file:
    for line in file_line:
        if not line.startswith('#') and len(line.strip()) > 0:
            cur_file = '%s/%s' % (cur_path,
                                  line if '?' not in line else line.rsplit('?', 1)[0])
            if '.m3u8' in line:
                handle_m3u8(cur_file)
            else:
                if not os.path.exists(cur_file):
                    line = '#%s' % line
        print(line)
        # file.write('%s\n' % line)


if __name__ == '__main__':
    help_msg = '''\
        Usage:python3 %s {option}
        -m: dirname         | mkdir dirname
        -r: oname nname | rename oname to nname
        -d: dirname          | delete dir
        -t: test
        --july: path    | update_july_data
        --july_src: filepath
        --flsav_src filepath
        --521av_src filepath
        --download_backend: path | download_backend
        --local: path   | load local m3u8
        --update_fls
        ---------------------------------------------------------
        [require]
        pip3 install SQLAlchemy==1.3.15 -i https://pypi.tuna.tsinghua.edu.cn/simple
        ''' % sys.argv[0]
    print(sys.argv)
    if len(sys.argv) < 2:
        print(help_msg)
    else:
        settings.get_config('dev')
        set_logger()
        if '-m' == sys.argv[1]:
            dirname = sys.argv[2]
            if os.path.exists(dirname):
                raise BaseException('file %s exists' % dirname)
            db.init_db('dev')
            parent, name = dirname.rsplit('/', 1)
            makedir(parent, name)
            exit(0)
        if '-r' == sys.argv[1]:
            oname = sys.argv[2]
            nname = sys.argv[3]
            db.init_db('dev')
            rename(oname, nname)
            exit(0)
        if '-d' == sys.argv[1]:
            dirname = sys.argv[2]
            db.init_db('dev')
            delete_by_path(dirname)
            exit(0)
        if '--july' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            update_july_data(sys.argv[2])
            exit(0)
        if '--july_src' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            import_july_data(sys.argv[2])
            exit(0)
        if '--flsav_src' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            import_fuliseav_data(sys.argv[2])
            exit(0)
        if '--521av_src' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            import_521_data(sys.argv[2])
            exit(0)
        if '--local' == sys.argv[1] and len(sys.argv) == 3:
            db.init_db('dev')
            load_local(sys.argv[2])
            exit(0)
        if '-t' == sys.argv[1]:
            # url = 'https://s19.xyz/video/view/eympOn3rAoMNa7Vq'
            # dom_path = [{'video': {'attr': {'id': 'video-play'}, 'string': ''}}]
            # get_res = {'attrs': ['data-src', 'data-poster']}
            # result = load_src(url, dom_path, get_res)
            # print(result)
            db.init_db('dev')
            session = db.create_session()
            dir_ = '/root'
            print([item for item in session.query(db.Hlsitem).filter(
                db.Hlsitem.path.like('%s%%' % dir_), db.Hlsitem.status == 0)])
            exit(0)
        # --update_fls
        if '--update_fls' == sys.argv[1]:
            db.init_db('dev')
            update_fuliseav_data()
            exit(0)
        print(help_msg)
